package com.dyApi.business.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dyApi.business.service.KsApiService;
import com.dyApi.business.service.dto.Amount;
import com.dyApi.business.service.dto.OrderConfirmInDto;
import com.dyApi.business.service.dto.SetCouponInDto;
import com.dyApi.business.service.dto.SetCouponOutDto;
import com.dyApi.utils.RedisUtils;
import com.kuaishou.locallife.open.api.client.KsLocalLifeAccessTokenClient;
import com.kuaishou.locallife.open.api.client.oauth.OAuthAccessTokenKsClient;
import com.kuaishou.locallife.open.api.KsLocalLifeApiException;
import com.kuaishou.locallife.open.api.domain.locallife_shop.OpenApiPoiShopPoiRespData;
import com.kuaishou.locallife.open.api.domain.locallife_third_code.*;
import com.kuaishou.locallife.open.api.domain.openapi.CipherInfoRequest;
import com.kuaishou.locallife.open.api.domain.openapi.CipherInfoResponse;
import com.kuaishou.locallife.open.api.request.locallife_order.GoodlifeV1TradeOrderQueryRequest;
import com.kuaishou.locallife.open.api.request.locallife_shop.GoodlifeV1ShopPoiQueryRequest;
import com.kuaishou.locallife.open.api.request.locallife_trade.GoodlifeV1FulfilmentCertificateVerifyRequest;
import com.kuaishou.locallife.open.api.request.openapi.GoodlifeSecurityDecryptBatchRequest;
import com.kuaishou.locallife.open.api.response.locallife_order.GoodlifeV1TradeOrderQueryResponse;
import com.kuaishou.locallife.open.api.response.locallife_shop.GoodlifeV1ShopPoiQueryResponse;
import com.kuaishou.locallife.open.api.response.locallife_trade.GoodlifeV1FulfilmentCertificateVerifyResponse;
import com.kuaishou.locallife.open.api.response.oauth.KsAccessTokenPreviousVersionResponse;
import com.kuaishou.locallife.open.api.response.openapi.GoodlifeSecurityDecryptBatchResponse;
import io.netty.util.internal.StringUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
@RequiredArgsConstructor
public class KsApiServiceImpl implements KsApiService {

    @Value("${ks-api.appKey}")
    private String appKey;

    @Value("${ks-api.appSecret}")
    private String appSecret;

    @Value("${ks-api.url}")
    private String ksApiUrl;

    @Value("${ks-api.refreshToken}")
    private String refreshTokenUrl;

    @Value("${ks-api.accessToken}")
    private String accessTokenUrl;

    @Value("${ks-api.accountId}")
    private String accountId;

    @Value("${ks-api.code}")
    private String code;

    @Value("${sync.url}")
    private String syncUrl;

    @Value("${sync.order}")
    private String syncOrder;

    @Value("${sync.setOrder}")
    private String setOrderUrl;

    @Value("${sync.refund}")
    private String refundUrl;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public Map<String, Object> poi() {
        Map<String, Object> res = new HashMap<>();
        String accessToken = getAccessToken();
        if (StringUtils.isEmpty(accessToken)) {// token无
            return res;
        }

        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
                .setAccessToken(accessToken)
                .build();

        GoodlifeV1ShopPoiQueryRequest request = new GoodlifeV1ShopPoiQueryRequest();

        request.setAccount_id(Long.valueOf(accountId));
        request.setSize(100);
        request.setPage(1);

        try {
            GoodlifeV1ShopPoiQueryResponse response = client.execute(request);
            if (ObjectUtil.isNotEmpty(response.getData()) && response.getData().getError_code() == 0) {
                OpenApiPoiShopPoiRespData data = response.getData();
                // Create a JSON object
                JSONObject json = (JSONObject) JSON.toJSON(data);
                // Convert the JSON object to a Map
                res = (Map<String, Object>) json;
            }
        } catch (KsLocalLifeApiException e) {}

        return res;

    }

    @Override
    public Map<String, Object> orderConfirm(OrderConfirmInDto inDto) {
        // xiangyingjieguo
        Map<String, Object> res = new HashMap<>();
        // 拼接请求服务数据
        Map<String, Object> req = new HashMap<>();
        // 基础信息
        req.put("createUserId", "13");
        req.put("orderFrom", 6);
        // 订单ID
        req.put("orderSn", inDto.getIdempotent_id());
        // 联系人信息
//        String username = "";
//        Long modileno = 0l;
//        if(ObjectUtil.isNotEmpty(inDto.getContact())) {
//            username = StringUtils.isEmpty(inDto.getContact().getEncrypt_name()) ? "" : decrypt(inDto.getContact().getEncrypt_name());
//            modileno = StringUtils.isEmpty(inDto.getContact().getEncrypt_phone()) ? 0l : Long.valueOf(decrypt(inDto.getContact().getEncrypt_phone()));
//        } else if(CollectionUtil.isNotEmpty(inDto.getTourists())) {
//            username = StringUtils.isEmpty(inDto.getTourists().get(0).getEncrypt_name()) ? "" : decrypt(inDto.getTourists().get(0).getEncrypt_name());
//            modileno = StringUtils.isEmpty(inDto.getTourists().get(0).getEncrypt_phone()) ? 0l : Long.valueOf(decrypt(inDto.getTourists().get(0).getEncrypt_phone()));
//        }

//        if (StringUtils.isEmpty(username) || modileno == 0l) {
//            Data data = new Data();
//            data.setError_code(-1l);
//            data.setDescription("缺少联系人姓名或联系方式！");
//            data.setResult(2);
//            data.setFail_code(10);
//            res.put("data", data);
//            return res;
//        }
        req.put("userName", "张三");
        req.put("mobileno", 13300000000l);

        // 商品及金额信息
        Integer count = inDto.getCount();
        // 票务信息
        List<Map<String, Object>> tickets = new ArrayList<>();
        Map<String, Object> ticket = new HashMap<>();
        ticket.put("id",inDto.getOut_id());
        ticket.put("buyNum", inDto.getCount());
        if (ObjectUtil.isEmpty(inDto.getAmount()) || ObjectUtil.isEmpty(inDto.getAmount().getPay_amount())) {
            Data data = new Data();
            data.setError_code(-1l);
            data.setDescription("缺少pay_amount！");
            data.setResult(2);
            data.setFail_code(10);
            res.put("data", data);
            return res;
        }
        Amount amount = inDto.getAmount();
        String rAmount = String.valueOf(amount.getPay_amount() / 100.0);
        req.put("amount", rAmount);
        String price = String.valueOf(amount.getPay_amount()/Double.valueOf(inDto.getCount())/100.0);
        ticket.put("settlePrice", price);
        ticket.put("buyPrice", price);
        tickets.add(ticket);
        req.put("tickets", tickets);
        // 请求三方接口
        HttpResponse httpResponse = HttpRequest.post(syncUrl + syncOrder)
                .body(JSONUtil.toJsonStr(req))
                .execute();
        int status = httpResponse.getStatus(); //获取响应码
        String body = httpResponse.body(); //获取响应内容
        if (status != HttpStatus.HTTP_OK) {
            Data data = new Data();
            data.setError_code(-1l);
            data.setDescription("商户异常！");
            data.setResult(2);
            data.setFail_code(9);
            res.put("data", data);
            return res;
        }
        // 响应结果
        Map<String, Object> map = JSONUtil.parseObj(body);
        if ((int) map.get("code") != 0) {
            Data data = new Data();
            data.setError_code(-1l);
            data.setDescription("商户异常！");
            data.setResult(2);
            data.setFail_code(9);
            res.put("data", data);
            return res;
        }
        Map<String, Object> reqData = (Map<String, Object>)map.get("data");
        redisUtils.set(inDto.getIdempotent_id(), String.valueOf(reqData.get("orderId")));
        // 成功直接返回
        Data data = new Data();
        data.setError_code(0l);
        data.setDescription("success");
        data.setResult(1);
        res.put("data", data);

        return res;
    }

    @Override
    public Map<String, Object> setCoupon(SetCouponInDto inDto) {
        Map<String, Object> res = new HashMap<>();
        // 拼接请求服务数据
        Map<String, Object> req = new HashMap<>();
//        String orderId = String.valueOf(inDto.getOrder_id());
        req.put("orderId", redisUtils.get(String.valueOf(inDto.getOrder_id())));
        // 请求三方接口
        HttpResponse httpResponse = HttpRequest.post(syncUrl + setOrderUrl)
                .body(JSONUtil.toJsonStr(req))
                .execute();
        int status = httpResponse.getStatus(); //获取响应码
        if (status != HttpStatus.HTTP_OK) {
            SetCouponOutDto outDto = new SetCouponOutDto();
            outDto.setError_code(-1l);
            outDto.setDescription("服务商接口请求失败！");
            outDto.setResult(2);
            res.put("data", outDto);
            return res;
        }
        // 响应结果
        String body = httpResponse.body(); //获取响应内容
        Map<String, Object> map = JSONUtil.parseObj(body);
        if ((int) map.get("code") != 0) {
            SetCouponOutDto outDto = new SetCouponOutDto();
            outDto.setError_code(-1l);
            outDto.setDescription("服务商接口请求失败！");
            outDto.setResult(2);
            res.put("data", outDto);
            return res;
        }
        // 正常处理
        List<String> codes = (List<String>)map.get("codes");
        List<String> qrcodes = (List<String>)map.get("qrcodes");

        List<CodeInfo> codeInfos = IntStream.range(0, codes.size())
                .mapToObj(i -> {
                    CodeInfo codeInfo = new CodeInfo();
                    codeInfo.setCode(codes.get(i));
                    codeInfo.setCode_redirect(codes.get(i));
                    return codeInfo;
                })
                .collect(Collectors.toList());
        // 返回
        SetCouponOutDto data = new SetCouponOutDto();
        data.setError_code(0l);
        data.setDescription("success");
        data.setResult(1);
        data.setCodes(codes);
        data.setCodes_list(codeInfos);
        res.put("data", data);
//        System.out.println("==========================");
//        System.out.println(JSON.toJSONString(codeInfos));
        return res;
    }

    @Override
    public Map<String, Object> refund(RefundAuditRequestData inDto) {
        Map<String, Object> res = new HashMap<>();
        // 拼接请求服务数据
        Map<String, Object> req = new HashMap<>();
        req.put("orderId", redisUtils.get(String.valueOf(inDto.getOrder_id())));
        req.put("orderSn", "");
        req.put("refundId", inDto.getTrade_no());

        List<String> voucherList = inDto.getCertificates().stream().map(RefundAuditCertificate::getCode).collect(Collectors.toList());
        req.put("voucherList", voucherList);
        // 请求三方接口
        HttpResponse httpResponse = HttpRequest.post(syncUrl + refundUrl)
                .body(JSONUtil.toJsonStr(req))
                .execute();
        int status = httpResponse.getStatus(); //获取响应码
        if (status != HttpStatus.HTTP_OK) {
            RefundResponseData outDto = new RefundResponseData();
            outDto.setError_code(-1l);
            outDto.setDescription("商家处理异常！");
            outDto.setResult(2);
            outDto.setReason("商家处理异常！");
            res.put("data", outDto);
            return res;
        }
        // 响应结果
        String body = httpResponse.body(); //获取响应内容
        Map<String, Object> map = JSONUtil.parseObj(body);
        if ((int) map.get("code") != 0) {
            RefundResponseData outDto = new RefundResponseData();
            outDto.setError_code(-1l);
            outDto.setDescription("商家处理异常！");
            outDto.setResult(2);
            outDto.setReason("商家处理异常！");
            res.put("data", outDto);
            return res;
        }
        RefundResponseData outDto = new RefundResponseData();
        outDto.setError_code(0l);
        outDto.setDescription("success");
        outDto.setResult(1);
        res.put("data", outDto);
        return res;
    }

    @Override
    public GoodlifeV1TradeOrderQueryResponse order(GoodlifeV1TradeOrderQueryRequest inDto) {
        GoodlifeV1TradeOrderQueryResponse response = new GoodlifeV1TradeOrderQueryResponse();
        String accessToken = getAccessToken();
        if(StringUtils.isEmpty(accessToken)) {
            return response;
        }
        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
                .setAccessToken(accessToken)
                .build();

        try {
            return client.execute(inDto);
        } catch (KsLocalLifeApiException e) {
            // 处理异常
            return response;
        }
    }

    @Override
    public Map<String, Object> verify(GoodlifeV1FulfilmentCertificateVerifyRequest inDto) {
        Map<String, Object> res = new HashMap<>();
        Data data = new Data();
        String accessToken = getAccessToken();
        if(StringUtils.isEmpty(accessToken)) {
            data.setError_code(-1L);
            data.setDescription("accessToken获取失败=="+accessToken);
            data.setResult(-1);
            res.put("data", data);
            return res;
        }
        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
                .setAccessToken(accessToken)
                .build();
        try {
            System.out.println("核销收到参数：" + JSON.toJSONString(inDto));
            GoodlifeV1FulfilmentCertificateVerifyResponse response = client.execute(inDto);
            com.kuaishou.locallife.open.api.domain.locallife_trade.Data resData = response.getData();
            boolean flg = resData.getError_code() == 0 && CollectionUtil.isNotEmpty(resData.getVerify_results()) && resData.getVerify_results().get(0).getResult() == 0L;

            if(flg) {
                data.setError_code(0L);
                data.setDescription("success");
                data.setResult(0);
            } else {
                // 处理异常
                data.setError_code(-1L);
                data.setDescription(resData.getDescription());
                data.setResult(-1);
            }
            res.put("data", data);
            return res;
        } catch (KsLocalLifeApiException e) {
            // 处理异常
            data.setError_code(-1L);
            data.setDescription("快手验券api请求失败");
            data.setResult(-1);
            res.put("data", data);
            return res;
        }
    }

    private String getAccessToken() {

        String accessToken = "";
        // 校验redis中是否存在access_token
        System.out.println("==="+redisUtils.get("ACCESS_TOKEN"));
        if (ObjectUtil.isEmpty(redisUtils.get("ACCESS_TOKEN"))) {// 获取access_token
            // 如果有refresh_token就用refresh_token获取，没有就重新获取
            System.out.println("ObjectUtil.isNotEmpty(redisUtils.get(\"REFRESH_TOKEN\")):"+ObjectUtil.isNotEmpty(redisUtils.get("REFRESH_TOKEN")));
            if (ObjectUtil.isNotEmpty(redisUtils.get("REFRESH_TOKEN"))) {
                OAuthAccessTokenKsClient client = new OAuthAccessTokenKsClient(appKey, appSecret);
                String refreshToken = String.valueOf(redisUtils.get("REFRESH_TOKEN"));
                System.out.println("refreshToken = " + refreshToken);
                KsAccessTokenPreviousVersionResponse response = null;
                try {
                    response = client.refreshAccessToken(refreshToken);
                    System.out.println(JSON.toJSONString(response));
                } catch (KsLocalLifeApiException e) {}
                // 结果验证
                if(response.getResult() == 1) {// 成功
                    accessToken = response.getAccessToken();
                    long expiresIn = response.getExpiresIn();
                    System.out.println("accessToken:"+accessToken);
                    redisUtils.set("ACCESS_TOKEN", accessToken, expiresIn, TimeUnit.SECONDS);
                }
            } else {
                OAuthAccessTokenKsClient client = new OAuthAccessTokenKsClient(appKey, appSecret);
                try {
                    KsAccessTokenPreviousVersionResponse response = client.getAccessToken(code);
                    if(response.getResult() == 1) {
                        accessToken = response.getAccessToken();
                        String refreshToken = response.getRefreshToken();
                        redisUtils.set("ACCESS_TOKEN", accessToken, response.getExpiresIn(), TimeUnit.SECONDS);
                        redisUtils.set("REFRESH_TOKEN", refreshToken, response.getRefreshTokenExpiresIn(), TimeUnit.SECONDS);
                    }
                } catch (KsLocalLifeApiException e) {}
            }
        } else {
            accessToken = String.valueOf(redisUtils.get("ACCESS_TOKEN"));
        }

        return accessToken;

    }

    private String decrypt(String cipherTxt) {
        String accessToken = getAccessToken();
        if (StringUtils.isEmpty(accessToken)) {
            return StringUtil.EMPTY_STRING;
        }

        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
                .setAccessToken(accessToken)
                .build();

        GoodlifeSecurityDecryptBatchRequest request = new GoodlifeSecurityDecryptBatchRequest();

        List<CipherInfoRequest> list1 = new ArrayList<>();
        CipherInfoRequest obj1 = new CipherInfoRequest();
        obj1.setCipher_text(cipherTxt);
        list1.add(obj1);
        request.setCipher_infos(list1);

        try {
            GoodlifeSecurityDecryptBatchResponse response = client.execute(request);
            if (ObjectUtil.isEmpty(response.getData()) || response.getData().getError_code() != 0) {
                return StringUtil.EMPTY_STRING;
            }
            List<CipherInfoResponse> cipherInfos = response.getData().getCipher_infos();
            if(CollectionUtil.isEmpty(cipherInfos)) {
                return StringUtil.EMPTY_STRING;
            }
            return cipherInfos.get(0).getDecrypt_text();
        } catch (KsLocalLifeApiException e) {
            // 处理异常
            return StringUtil.EMPTY_STRING;
        }
    }

}
